package net.wangds.common.web.fileupload.comp;

import net.wangds.common.base.module.Holder;
import net.wangds.common.web.fileupload.module.FileBytes;
import net.wangds.common.web.fileupload.module.FileUploadData;
import net.wangds.common.web.fileupload.module.UploadFileEntity;
import net.wangds.common.web.fileupload.repository.db.UploadFileRepo;
import net.wangds.common.web.fileupload.viewmodel.form.FileUploadForm;
import net.wangds.log.helper.LogHelper;
import net.wangds.utils.FileUtils;
import net.wangds.utils.Md5Utils;
import net.wangds.web.utils.UploadUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.io.File;
import java.nio.ByteBuffer;
import java.util.List;
import java.util.Objects;
import java.util.Optional;

/**
 * .
 * <p></p>
 *
 * @author 王东石 2020/5/15 13:23.
 */
@Component
public class FileUploadComp {
    private static File FILE_PARENT_DIR = new File(System.getProperty("use.home"), "uploads");

    static {
        if(!FILE_PARENT_DIR.exists()){
            if(!FILE_PARENT_DIR.mkdirs()){
                LogHelper.warn("保存上传文件的目录不存在，且无法创建,"+FILE_PARENT_DIR.getPath());
            }
        }
    }

    @Autowired
    private UploadFileRepo mmJpaUpld;


    /**
     * 保存新上传的文件.
     * <p>md5和size都相同的文件，只保存一个文件.</p>
     * @param form form.
     * @return 记录.
     */
    public Optional<UploadFileEntity> upload(FileUploadData form) {
        Objects.requireNonNull(form);
        byte[] data = form.getContent();
        String md5 = Md5Utils.md5(data);
        long size= form.getSize();
        List<UploadFileEntity> ls = mmJpaUpld.findByMd5AndSize(md5,size);

        if(CollectionUtils.isEmpty(ls)||isExistsFile(md5, size)){

            String filename = md5+"_"+form.getSize();

            File out = new File(FILE_PARENT_DIR, filename);

            FileUtils.writeFile(out, data, false);

        }

        Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        String loginname = null;
        if(principal!=null){
            loginname = principal.toString();
        }


        UploadFileEntity entity = UploadFileEntity.builder()
                .filename(form.getFilename())
                .fileTm(form.getFileTm())
                .fileOwner(loginname)
                .md5(md5)
                .size(form.getSize())
                .type(form.getType())
                .build();


        entity = mmJpaUpld.saveAndFlush(entity);

        return Optional.of(entity);
    }

    /**
     * 保存新上传的文件.
     * <p>md5和size都相同的文件，只保存一个文件.</p>
     * @param form form.
     * @return 记录.
     */
    public Optional<UploadFileEntity> upload(FileUploadForm form) {
        Objects.requireNonNull(form);

        byte[] data = UploadUtils.readUrlContent(form.getContent());
        return upload(FileUploadData.builder().content(data)
                .filename(form.getFilename()).fileTm(form.getFileTm())
                .size(form.getSize()).type(form.getType()).build());
    }

    public boolean isExistsFile(String md5, long fileSize){
        return new File(FILE_PARENT_DIR,
                md5 + "_" + fileSize).exists();
    }

    public boolean isExistsFile(String fileId){
        Holder<Boolean> hld = Holder.of(false);


        mmJpaUpld.findById(fileId).ifPresent(entity-> hld.target = new File(FILE_PARENT_DIR,
                entity.getMd5() + "_" + entity.getSize()).exists());
        return hld.target;
    }

    public FileBytes loadFile(String id){
        Holder<FileBytes> hld = Holder.of(null);


        mmJpaUpld.findById(id).ifPresent(entity->{


            ByteBuffer buff = FileUtils.readFile(
                    new File(FILE_PARENT_DIR,
                            entity.getMd5() + "_" + entity.getSize()));


            byte[] array = buff.array();
            
            hld.target = FileBytes.builder()
                    .filename(entity.getFilename())
                    .size(entity.getSize())
                    .type(entity.getType())
                    .content(array)
                    .build();
        });
        return hld.target;
    }

}
